import  {JoystickType, DirectionType}  from './JoystickCommon'
import { GlobalEvent } from '../../Script/base/GlobalEvent';
import { ConstData } from '../../Script/base/ConstData';

const { ccclass, property } = cc._decorator;

@ccclass
export default class joystick extends cc.Component {

    @property({
        type: cc.Node,
        displayName: 'Dot',
        tooltip: '摇杆操纵点'
    })
    dot: cc.Node = null;

    @property({
        type: cc.Node,
        displayName: 'Ring',
        tooltip: '摇杆背景节点',
    })
    ring: cc.Node = null;

    @property({
        type: JoystickType,
        displayName: 'Touch Type',
        tooltip: '触摸类型',
    })
    joystickType: number = JoystickType.FIXED;

    @property({
        type: DirectionType,
        displayName: 'Direction Type',
        tooltip: '方向类型',
    })
    directionType: number = DirectionType.ALL;

    private _radius:number = 0;
    private _stickPos: cc.Vec2 = null;
    private _touchLocation: cc.Vec2 = null;
    private _curkeyDir:cc.Vec2[] = [];
    private _keyDir:cc.Vec2[] = [];

    onLoad() {
        this._radius = this.ring.width / 2;
        this._initTouchEvent();
        // hide joystick when follow
        if (this.joystickType == JoystickType.FOLLOW) {
            this.node.opacity = 0;
        }

        this._keyDir[cc.macro.KEY.a] = cc.v2(-1,0);
        this._keyDir[cc.macro.KEY.w] = cc.v2(0,1);
        this._keyDir[cc.macro.KEY.d] = cc.v2(1,0);
        this._keyDir[cc.macro.KEY.s] = cc.v2(0,-1);
    }

    _initTouchEvent() {
        this.node.on(cc.Node.EventType.TOUCH_START, this._touchStartEvent, this);
        this.node.on(cc.Node.EventType.TOUCH_MOVE, this._touchMoveEvent, this);
        this.node.on(cc.Node.EventType.TOUCH_END, this._touchEndEvent, this);
        this.node.on(cc.Node.EventType.TOUCH_CANCEL, this._touchEndEvent, this);

        cc.systemEvent.on(cc.SystemEvent.EventType.KEY_DOWN, this._onKeyDown, this);
        cc.systemEvent.on(cc.SystemEvent.EventType.KEY_UP, this._onKeyUp, this);
    }

    _emitKeyDir(){
        var _dir = cc.v2(0,0);
        for(var index in this._curkeyDir){
            if(this._curkeyDir[index] == null) continue;
            _dir = _dir.add(this._curkeyDir[index]);
        }
        _dir.normalizeSelf();
        if(_dir.equals(cc.v2(0,0)))
            GlobalEvent.emit(GlobalEvent.Event.joyStickStop);
        else
            GlobalEvent.emit(GlobalEvent.Event.joyStickDir, {Dir:_dir});
    }

    _onKeyDown(event){
        this._curkeyDir[event.keyCode] = (this._keyDir[event.keyCode]);
        this._emitKeyDir();
    }

    _onKeyUp(event){
        this._curkeyDir[event.keyCode] = null;
        this._emitKeyDir();
    }

    _touchStartEvent(event) {
        const touchPos = this.node.convertToNodeSpaceAR(event.getLocation());

        if (this.joystickType === JoystickType.FIXED) {
            this._stickPos = this.ring.getPosition();

            // 触摸点与圆圈中心的距离
            const distance = touchPos.sub(this.ring.getPosition()).mag();

            // 手指在圆圈内触摸,控杆跟随触摸点
            if (this._radius > distance) {
                this.dot.setPosition(touchPos);
            }
        } else if (this.joystickType === JoystickType.FOLLOW) {

            // 记录摇杆位置，给 touch move 使用
            this._stickPos = touchPos;
            this.node.opacity = 255;
            this._touchLocation = event.getLocation();

            // 更改摇杆的位置
            this.ring.setPosition(touchPos);
            this.dot.setPosition(touchPos);
        }

        GlobalEvent.emit(GlobalEvent.Event.joyStickStart);
    }

    _touchMoveEvent(event) {
        if (this.joystickType === JoystickType.FOLLOW) {
            // 如果 touch start 位置和 touch move 相同，禁止移动
            if (this._touchLocation === event.getLocation()) {
                return false;
            }
        }

        // 以圆圈为锚点获取触摸坐标
        const touchPos = this.ring.convertToNodeSpaceAR(event.getLocation());
        const distance = touchPos.mag();

        // 由于摇杆的 postion 是以父节点为锚点，所以定位要加上 touch start 时的位置
        const posX = this._stickPos.x + touchPos.x;
        const posY = this._stickPos.y + touchPos.y;

        // 归一化
        const p = cc.v2(posX, posY).sub(this.ring.getPosition()).normalize();

        if (this._radius > distance) {
            this.dot.setPosition(cc.v2(posX, posY));
        } else {
            // 控杆永远保持在圈内，并在圈内跟随触摸更新角度
            const x = this._stickPos.x + p.x * this._radius;
            const y = this._stickPos.y + p.y * this._radius;
            this.dot.setPosition(cc.v2(x, y));
        }

        GlobalEvent.emit(GlobalEvent.Event.joyStickDir, {Dir:p});
    }

    _touchEndEvent() {
        this.dot.setPosition(this.ring.getPosition());
        if (this.joystickType == JoystickType.FOLLOW) {
            this.node.opacity = 0;
        }

        GlobalEvent.emit(GlobalEvent.Event.joyStickStop);
    }
}
